<script setup>
import { ref, nextTick, watch } from 'vue'
import UploadExcel from '@/components/UploadExcel.vue'
import { utils } from 'xlsx'
import { ElMessage } from 'element-plus'
import {
  readSheetShJS,
  readWorkbookShJS
} from '@/utils/ExcelUtils.js'
import { loadingWrapper } from '@/utils/LoadingUtils.js'
import { usePriceSummaryStore } from '@/stores/index.js'
import * as GC from '@grapecity/spread-sheets'
import * as ExcelIO from '@grapecity/spread-excelio'
import { useFactoryPromise } from '@promises/factory/factoryPromise.js'
import { useModelPromise } from '@promises/model/modelPromise.js'
import { saveAs } from 'file-saver'
import { Pagination } from 'swiper/modules'
import dayjs from 'dayjs'
import FieldsDiag from '@/views/PriceSummary/components/FieldsDiag.vue'
import _ from 'lodash'
import { Close, Select } from '@element-plus/icons-vue'

const priceSummaryStore = usePriceSummaryStore()
priceSummaryStore.resetFields()

const form = ref({
  excelName: '',
  dataSheet: '',
  templateName: '',
  modelTempSheet: '',
  factoryTempSheet: '',
  manager: '',
  selectedContracts: []
})

const sheets = ref([])

function resetTransfer() {
  form.value.selectedContracts = []
  transferData.value = []
  transferRef.value?.clearQuery('left')
  transferRef.value?.clearQuery('right')
}

const handleUploadChange = (uploadFile) => {
  const fn = async () => {
    const ab = await uploadFile.raw.arrayBuffer()
    form.value.excelName = uploadFile.name
    form.value.dataSheet = ''
    sheets.value = readWorkbookShJS(ab, { bookSheets: true }).SheetNames
      .map(item => {
        if (item === '已完成总表') {
          form.value.dataSheet = item
          fn.postFn = handleSelectChange
          fn.postArgs = [item]
        }
        return { label: item, value: item }
      })

    resetTransfer()
  }
  loadingWrapper(fn, '正在读取工作表')
}

const prevDataSheet = ref('')
watch(() => form.value.dataSheet, (newVal, prevVal) => prevDataSheet.value = prevVal, { immediate: true, flush: 'pre' })

let headerArr = []
const handleSelectChange = (value, checkChange = true) => {
  const fn = async (value, checkChange) => {
    // console.log('value', value)
    resetTransfer()
    const ab = await uploadRef.value.uploadFileExp?.raw.arrayBuffer()
    // console.log(value)
    //读取表头
    const headerRange = readSheetShJS(ab, { sheetRows: 2 }, value)
    //读取第二行作为header, values 作为整体的header
    const headerArrRaw = utils.sheet_to_json(headerRange, { header: 1 })
    // console.log(headerArrRaw)
    headerArr = headerArrRaw[headerArrRaw.length - 1]
      .filter(item => !_.isEmpty(item))
      .map(item => item.toString().replace(/\s/g, ''))
    // console.log(headerArr)
    if (!headerArr.some(header => header === '合同号')) {
      ElMessage.error('无合同号字段, 请检查模板是否正确!')
      form.value.dataSheet = ''
    }
    // console.log('value', value)
    // console.log('prevDataSheet.value', prevDataSheet.value)
    if (checkChange && value !== prevDataSheet.value) {
      priceSummaryStore.resetFields()
      // console.log('resetFields')
    }
    // console.log(priceSummaryStore.fields)
    // console.log('entries', priceSummaryStore.fields.entries())
    const data = utils.sheet_to_json(readSheetShJS(ab, {}, value), { header: headerArr, range: 2, raw: false })
    // const data = utils.sheet_to_json(readSheet(ab, {}, value), { header: headerArr, dateNF: 'YYYY-mm-DD', UTC: true,  })
    priceSummaryStore.setPriceSummaryData(data)
    // console.log('data', priceSummaryStore.priceSummaryData)
    generateTransferData()
  }
  loadingWrapper(fn, '正在读取已完成总表', value, checkChange)
}

const transferData = ref([])
const generateTransferData = () => {
  transferData.value = priceSummaryStore.contracts?.map(item => {
    return {
      key: item,
      label: item,
      disabled: false
    }
  })
}

const filterMethod = (query, item) => {
  return item.key?.includes(query)
}
const transferRef = ref(null)
const uploadRef = ref(null)
const uploadTempRef = ref(null)
// onMounted(() => {
//   // console.log(transferRef.value)
// })

let tempSheets = []
const handleTempUploadChange = async (uploadFile) => {
  const ab = await uploadFile.raw.arrayBuffer()
  form.value.templateName = uploadFile.name
  form.value.modelTempSheet = ''
  form.value.factoryTempSheet = ''
  tempSheets = readWorkbookShJS(ab, { bookSheets: true }).SheetNames
    .map(item => {
      if (item === '单款核价单-模板') {
        form.value.modelTempSheet = item
      } else if (item === '工厂账单表-模板') {
        form.value.factoryTempSheet = item
      }
      return { label: item, value: item }
    })
  //上传完模板文件就立刻加载
  let excelIo = new ExcelIO.IO()
  let excelFile = uploadTempRef.value.uploadFileExp.raw
  excelIo.open(
    excelFile,
    async (json) => {
      await workbookTemp.fromJSON(json)
    },
    error => {
      console.error(error)
      ElMessage.error('模板文件加载失败')
    }
  )
}

const handleTempSelectChange = (value) => {
  // console.log(value)
  workbookTemp.setActiveSheet(value)
  workbookTemp.refresh()
}

const { getFactoryTSPromise } = useFactoryPromise()
const { getModelTSPromise } = useModelPromise()

const fieldsDiagRef = ref(null)
const fieldsNotMatched = ref([])
const openDiag = () => {
  fieldsDiagRef.value.open(() => fieldsNotMatched.value = [], null)
}

const formRef = ref(null)
const generate = () => {
  const fn = () => {
    // console.log(selectedContracts.value)
    formRef.value.validate(async (valid, fields) => {
      if (!valid) {
        ElMessage.error('请检查表单是否填写正确!')
        return
      }
      fieldsNotMatched.value = []
      for (const [key, value] of priceSummaryStore.fields.entries()) {
        if (!headerArr.includes(value)) {
          fieldsNotMatched.value.push(key)
        }
      }
      // console.log(fieldsNotMatched)
      if (fieldsNotMatched.value.length > 0) {
        await nextTick(() => {
          openDiag()
        })
        return
      }
      submit()
    })
  }
  const submit = () => {
    const raw = priceSummaryStore.priceSummaryData.filter(item => {
      return form.value.selectedContracts.some(contract => contract === item['合同号'])
    })
    // console.log('pData', priceSummaryStore.priceSummaryData)
    // console.log('raw', raw)
    // console.log('raw.length', raw.length)

    // 清空所有 Sheet
    while (workbook.getSheetCount() > 0) {
      workbook.removeSheet(0) // 逐个移除 Sheet
    }

    let promiseArr = []
    tempSheetProcess(promiseArr, form.value.manager, raw, form.value.modelTempSheet, '_1', getModelTSPromise)
    tempSheetProcess(promiseArr, form.value.manager, raw, form.value.factoryTempSheet, '_2', getFactoryTSPromise)

    Promise.all(promiseArr).then(() => {
      sortWorksheetsByName(workbook, true)
      workbook.refresh()
      goNext()
    }).catch(error => {
      console.error('处理 Promise 时出错:', error)
      ElMessage.error('生成失败, 原因:' + error)
    })
  }
  loadingWrapper(fn, '正在生成, 请稍后...')
}

const swiperInstance = ref(null)
const onSwiperInit = (swiper) => {
  swiperInstance.value = swiper // 初始化时保存实例
  // console.log('Swiper 实例:', swiper); // 确认是否获取成功
}
const goNext = async () => {
  await nextTick() // 等待 Vue 更新 DOM
  // console.log('swiperInstance', swiperInstance)
  if (swiperInstance.value) {
    swiperInstance.value.slideNext() // 直接使用实例
  }
}

let workbook = null
let workbookTemp = null

function initResult(spreadResult) {
  workbook = spreadResult
}

function initTemp(spreadTemp) {
  workbookTemp = spreadTemp
}

const tempSheetProcess = (promiseArr, manager, raw, tempSheetName, postFix, getTSPromise, pool) => {
  const sheetCount = workbook.getSheetCount()
  workbook.setSheetCount(form.value.selectedContracts.length + sheetCount)

  for (let i = 0; i < form.value.selectedContracts.length; i++) {
    const contract = form.value.selectedContracts[i]
    // console.log('contract', contract)
    const data = {
      contract,
      manager,
      date: new Date().toISOString().split('T')[0],
      curRC: { r: 0, c: 0 },
      tempSheetName,
      tempSheetNewName: `${contract}${postFix}`,
      raw,
    }
    const tempSheet = workbookTemp.getSheetFromName(data.tempSheetName)
    // console.log(workbook.getSheetCount())
    const tempSheetJsonStr = JSON.stringify(tempSheet.toJSON({
      ignoreStyle: false,
      ignoreFormula: false
    }))
    // console.log(sheetCount  +  i)
    workbookTemp.getNamedStyles().forEach(function(namedStyle) {
      workbook.addNamedStyle(namedStyle)
    })
    let newSheet = workbook.getSheet(sheetCount + i)
    newSheet.fromJSON(JSON.parse(tempSheetJsonStr, {
      ignoreStyle: false,
      ignoreFormula: false,
      saveAsView: true,
      includeAutoMergedCells: true
    }))
    newSheet.name(data.tempSheetNewName)
    promiseArr.push(getTSPromise(newSheet, data))
  }
}

const download = () => {
  let excelIo = new ExcelIO.IO()
  let json = JSON.stringify(workbook.toJSON({
    ignoreStyle: false,
    ignoreFormula: false,
    saveAsView: true
  }))
  excelIo.save(json, blob => {
    const dateFormatted = dayjs().format('YYYY-MM-DD_HH:mm:ss')
    // console.log(dateFormatted)
    saveAs(blob, `核价单-${form.value.manager}-${dateFormatted}`)
  }, e => {
    console.error(e)
    ElMessage.error(e)
  }, {
    xlsxStrictMode: false
  })
}

const modules = [Pagination]
const pagination = {
  clickable: true
}

function sortWorksheetsByName(workbook, ascending = true) {
  let sheets = []
  for (let i = 0; i < workbook.getSheetCount(); i++) {
    sheets.push(workbook.getSheet(i))
  }
  sheets.sort((a, b) => {
    return ascending
      ? a.name().localeCompare(b.name())
      : b.name().localeCompare(a.name())
  })

  // 重新调整索引
  sheets.forEach((sheet, index) => {
    // console.log(sheet.name(), index)
    workbook.changeSheetIndex(sheet.name(), index)
  })
}

const rules = ref({
  manager: [
    { required: true, message: '请输入业务员姓名', trigger: 'blur' }
  ],
  excelName: [
    { required: true, message: '请上传包含已完成总表的excel 文件', trigger: 'blur' }
  ],
  dataSheet: [
    { required: true, message: '请选择包含已完成总表', trigger: 'blur' }
  ],
  selectedContracts: [
    {
      required: true, message: '请选择合同号', trigger: 'blur', validator: (rule, value, callback) => {
        // console.log('value', value)
        if (value.length === 0) {
          return callback(new Error('请选择合同号'))
        }
        return callback()
      }
    }
  ],
  templateName: [
    { required: true, message: '请上传包含核价单模板excel 文件', trigger: 'blur' }
  ],
  modelTempSheet: [
    { required: true, message: '请选择单款核价单模板sheet', trigger: 'blur' }
  ],
  factoryTempSheet: [
    { required: true, message: '请选择工厂账单表模板sheet', trigger: 'blur' }
  ]
})
</script>

<script>
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css'
import 'swiper/css/pagination'

export default {
  components: {
    Swiper,
    SwiperSlide
  }
}
</script>

<template>
  <div class="wrapper">
    <swiper :modules="modules" :pagination="pagination" :auto-height="true" class="swiper" space-between="40px"
            no-swiping-class="spread-host" ref="swiperRef" @swiper="onSwiperInit">
      <swiper-slide>
        <el-form :model="form" label-width="auto" :rules="rules" ref="formRef">
          <el-form-item label="业务员" prop="manager">
            <el-input v-model="form.manager" placeholder="请输入业务员姓名" class="excelName" />
          </el-form-item>
          <el-form-item label="已完成Excel文件" prop="excelName">
            <el-input v-model="form.excelName" disabled placeholder="请上传包含已完成总表的excel 文件"
                      class="excelName" />
            <upload-excel :handleChange="handleUploadChange" ref="uploadRef" class="upload-excel" />
          </el-form-item>
          <el-form-item label="已完成总表sheet" prop="dataSheet">
            <el-select v-model="form.dataSheet" placeholder="请选择已完成总表" style="width: 240px"
                       @change="handleSelectChange">
              <el-option
                v-for="item in sheets"
                :key="item.value"
                :label="item.label"
                :value="item.value"
                filterable
              />
            </el-select>
          </el-form-item>
          <el-form-item label="合同列表" prop="selectedContracts">
            <el-transfer
              v-model="form.selectedContracts"
              style="text-align: left; display: inline-block"
              filterable
              :filter-method="filterMethod"
              :titles="['所有合同', '已选合同']"
              :button-texts="['取消选择', '选择']"
              :data="transferData"
              ref="transferRef"
              filter-placeholder="请输入关键字"
            >
              <template #left-empty>
                <el-empty :image-size="60" description="无合同号" />
              </template>
              <template #right-empty>
                <el-empty :image-size="60" description="无选择合同号" />
              </template>
            </el-transfer>
          </el-form-item>
          <el-form-item label="核价单模板" prop="templateName">
            <el-input v-model="form.templateName" disabled placeholder="请上传包含核价单模板excel 文件"
                      class="excelName" />
            <upload-excel :handleChange="handleTempUploadChange" ref="uploadTempRef" :btnText='"选择模板文件"'
                          class="upload-excel" />
          </el-form-item>
          <el-form-item label="单款核价单模板sheet" prop="modelTempSheet">
            <el-select v-model="form.modelTempSheet" placeholder="请选择单款核价单模板sheet" style="width: 240px"
                       @change="handleTempSelectChange">
              <el-option
                v-for="item in tempSheets"
                :key="item.value"
                :label="item.label"
                :value="item.value"
                :disabled="item.key === form.factoryTempSheet"
                filterable
              />
            </el-select>
          </el-form-item>
          <el-form-item label="工厂账单表模板sheet" prop="factoryTempSheet">
            <el-select v-model="form.factoryTempSheet" placeholder="请选择工厂账单表模板sheet" style="width: 240px"
                       @change="handleTempSelectChange">
              <el-option
                v-for="item in tempSheets"
                :key="item.value"
                :label="item.label"
                :value="item.value"
                :disabled="item.key === form.modelTempSheet"
                filterable
              />
            </el-select>
          </el-form-item>
          <el-form-item label="模板字段映射" prop="fieldsReflect">
            <el-button type="primary" @click="openDiag">配置</el-button>
            <el-icon>
              <Close v-if="fieldsNotMatched.length > 0" color="red"/>
              <Select v-else color="green"/>
            </el-icon>
          </el-form-item>
        </el-form>
        <el-text class="mx-1">
          模板预览
        </el-text>
        <gc-spread-sheets class="spread-host" @workbookInitialized="initTemp" :scrollbar-max-align="true" />
        <el-button size="large" class="subBtn" @click="generate">
          生成
        </el-button>
        <FieldsDiag ref="fieldsDiagRef" :fieldsNotMatched="fieldsNotMatched" :headerArr="headerArr"/>
      </swiper-slide>
      <swiper-slide>
        <el-text class="mx-1" size="large">
          结果预览
        </el-text>
        <gc-spread-sheets class="spread-host" @workbookInitialized="initResult" />
        <el-button size="large" class="subBtn" @click="download()">
          下载
        </el-button>
      </swiper-slide>
    </swiper>
  </div>
</template>

<style scoped lang="scss">
.wrapper {
  margin: 0;
  width: 100%;
}

.subBtn {
  width: 100%;
  background: #409eff;
  color: #fff;
  border: none;
  margin-top: 20px;
  margin-bottom: 50px;
}

.excelName {
  width: 30%;
  margin-right: 10px;
}

.spread-host {
  width: 100%;
  height: 600px;
  margin-top: 15px
}

.swiper {
  width: 100%;
  height: 100%;

  .swiper-slide {
    font-size: 18px;
    padding: 20px;
  }
}

.el-form-item {
  align-items: center;
}

.upload-excel {
  display: flex;
  align-items: center;
}

.el-icon {
  font-size: 20px;
  margin: 0 10px;
}
</style>
